package bainuo

import groovy.sql.Sql

def execute() {
    def conn = null
    def conn2 = null
    def MySQL = null
    try {
        conn = Sql.newInstance(mypara.hqcon(2))
        conn2 = Sql.newInstance(mypara.hqcon(1))
        MySQL = Sql.newInstance("jdbc:mysql://10.1.1.209:3306/cpu_sourcing", "oper_dc", "operzADF2020qwer", "com.mysql.cj.jdbc.Driver")
        String sql = '''
                SELECT b.pk_praybill_b, CAST(b.crowno AS VARCHAR) + '$' + p.vbillcode AS crowno_vbillcode
                FROM po_praybill p
                INNER JOIN po_praybill_b b ON p.pk_praybill = b.pk_praybill 
                WHERE p.dr=0 
            '''
        def rows = conn.rows(sql)

        // 如果没有结果，立即返回
        if (!rows) {
            return ["state": 0, "Ascript": "无查询结果", "data": null]
        }
        def PkPraybillB_list = []
        def sql4 ="select PkPraybillB from PurchaseAttachments"
        conn2.eachRow(sql4){
            PkPraybillB_list.add(it.PkPraybillB)
        }
        // 遍历每一行并处理
        rows.each { row ->
            if (!PkPraybillB_list.contains(row.pk_praybill_b)){
                // 更新 MySQL 数据库中的 file_id 字段
                // 使用 erp_bill_code_no 进行匹配
                MySQL.execute("UPDATE ipu_pu_req SET file_id = ? WHERE erp_bill_code_no = ?", [row.pk_praybill_b, row.crowno_vbillcode])

                def fileId = selectFileId(row.crowno_vbillcode)
                // 创建一个包含当前行数据的列表，以便传递给 push 方法
                def currentRowList = [row]
                push(currentRowList, fileId)
//                println(row.crowno_vbillcode)
            }
//            else {
//                println("此pk_praybill_b已存在，跳过不执行"+row.pk_praybill_b)
//            }

        }
        return ["state": 1, "Ascript": "查询成功", "data": true]
    } catch (Exception e) {
        e.printStackTrace()
        return ["state": 0, "Ascript": "查询错误: ${e.message}", "data": false]
    } finally {
        if (conn != null) {
            conn.close()
        }
        if (conn2 != null) {
            conn2.close()
        }
        if (MySQL != null) {
            MySQL.close()
        }
    }
}


def selectFileId(def crowno_vbillcode) {
    def conn = null
    try {
        // 使用连接池或其他方式获取连接，避免硬编码连接信息
        conn = Sql.newInstance("jdbc:mysql://10.1.1.209:3306/cpu_sourcing", "oper_dc", "operzADF2020qwer", "com.mysql.cj.jdbc.Driver")

        String sqlStatement = "SELECT file_id FROM ipu_pu_req WHERE dr = 0 and erp_bill_code_no = ? LIMIT 1"
        def result = conn.firstRow(sqlStatement, [crowno_vbillcode])
        //println(crowno_vbillcode)

        // 使用 if-else 语句返回
        if (result != null && result.file_id != null) {
            return result.file_id;
        } else {
            return null;
        }
    } catch (Exception e) {
        // 记录日志而不直接暴露给用户
        log.error("Error in selectFileId for row ${row}: ${e.message}", e)
        return null // 或者你可以选择抛出异常，具体取决于你的错误处理策略
    } finally {
        if (conn != null) {
            conn.close()
        }
    }
}

import groovy.json.JsonSlurper

def push(def items,String fileId) {
    String _url = "nccloud/api/platform/attachmentcloudsync/queryAttachmentByBillId"

    items.each { item ->
        // 假设 item 是一个 Map 类型，其中包含 'pk_praybill_b' 键
        String pk_praybill_b = item.pk_praybill_b
        String _json = """
        {
            "billid":"${pk_praybill_b}",
            "op_type":[1]
        }
        """
//        System.out.println("Sending JSON for billid=${pk_praybill_b}: $_json")

        try {
            // 调用 TokenTest.openapi 方法
            String json = TokenTest.openapi(_url, _json)

            if (json == null || json.isEmpty()) {
                throw new Exception("Failed to get response from openapi")
            }

            def tokenData = new JsonSlurper().parseText(json)
            String accessToken = tokenData.data.access_token
//            System.out.println("Response JSON for billid=${pk_praybill_b}: $json")

            // 调用 TokenTest.openapi2 方法并获取返回值
            String _return = TokenTest.openapi2(_url, _json, json)
            if (_return == null || _return.isEmpty()) {
                throw new Exception("Failed to get response from openapi2")
            }
//            System.out.println("Return for billid=${pk_praybill_b}: $_return")

            // 解析返回的 JSON 以获取 pk_doc
            def returnData = new JsonSlurper().parseText(_return)

            if (!returnData.success){
                println("请求错误")
                return
            }
            if (!returnData.data){
                //println("文件不存在")
                return
            }
            if(returnData.data != null && returnData.data.size()> 0){
                for (def map:returnData.data){
                    def PKdoc = map.pk_doc
                    def FileName = map.filename
                    println(map.filename)
                    download(fileId,PKdoc,accessToken,FileName,pk_praybill_b)
                }
            }
        } catch (Exception e) {
            e.printStackTrace()
            System.err.println("Error processing billid=${pk_praybill_b}: ${e.message}")
        }
    }
}
import okhttp3.*

def download(String fileId,String pkDoc, String Token,String filename,String pk_praybill_b){
    OkHttpClient client = new OkHttpClient();

    MediaType mediaType = MediaType.parse("multipart/form-data; boundary=---011000010111000001101001");
    RequestBody body = RequestBody.create(mediaType, "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n\r\n-----011000010111000001101001--\r\n\r\n");
    Request request = new Request.Builder()
            .url("http://10.1.1.226:10088/nccloud/api/platform/attachmentcloudsync/download?pk_doc=${pkDoc}")
            .post(body)
            .addHeader("access_token", Token)
            .addHeader("client_id", "ESB")
            .addHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001")
            .build();

    // 发起请求并获取响应
    try (
            Response response = client.newCall(request).execute();  ) {

        // 确保请求成功
        if (response.isSuccessful()) {

            // 获取文件输入流
            InputStream inputStream = response.body().byteStream();
            upload(fileId,filename,inputStream,pk_praybill_b,pkDoc)

        } else {
            System.err.println("Request failed with code: " + response.code());
        }
    } catch (IOException e) {
        System.err.println("Error during request execution: " + e.getMessage());
    }
}

def upload(String fileId,String fileName,def inputStream,String pk_praybill_b,String pkDoc){

    String appKey = "d42bf79ccfcd49fa8c001f15b208b8cd";
    String appSecret = "7c70c9c39e70300e3496770e9c5bbffb47280dfc";
    String openApiUrl = "https://srm.bestcomm.cn:11443";
    Map paramMap = new HashMap();
    paramMap.put("appKey", appKey);
    paramMap.put("appSecret", appSecret);
    paramMap.put("openApiUrl", openApiUrl);
    paramMap.put("businessType", "diwork_yuncai");
    paramMap.put("businessId", fileId);
    paramMap.put("usePrivateBucket", "true");
    paramMap.put("fileName", fileName);
    paramMap.put("fileBase64", inputStreamToBase64(inputStream));
    Map uploadResult = BIPFormUtilTest.uploadFile(paramMap);
//    println(uploadResult)
    println(fileId)

    // 使用 JsonSlurper 解析 JSON 字符串（如果需要）
    JsonSlurper jsonSlurper = new JsonSlurper()
    Object parsedResult = jsonSlurper.parseText(uploadResult.data as String)

    // 检查是否有 'code' 字段，并且 code 是否等于 "200"
    if (parsedResult.code == "200") {
        // 进一步检查 data 中的成功计数
        Map data = parsedResult.data;
        if (data.successCount > 0 && data.failCount == 0) {
            println("文件上传成功")
            // 调用 insert 方法并传递必要的参数
            def insertResult = insert(pkDoc, fileName, pk_praybill_b)
            if (insertResult.state == 1) {
                println("数据库插入成功")
            } else {
                println("数据库插入失败: ${insertResult.Ascript}")
            }
        } else {
            println("文件上传部分失败或完全失败")
        }
    } else {
        println("服务器返回错误代码: ${parsedResult.code}")
    }
}
def insert(String pkDoc, String fileName, String pk_praybill_b) {
    def conn = null
    try {
        // 创建数据库连接
        conn = Sql.newInstance(mypara.hqcon(1))
        // 使用参数化查询防止 SQL 注入
        String sql = '''
            INSERT INTO PurchaseAttachments (PkDoc, FileName, PkPraybillB)
            VALUES (?, ?, ?);
        '''
        // 执行插入操作
        int updateCount = conn.executeUpdate(sql, [pkDoc, fileName, pk_praybill_b])
        // 检查是否有行被影响（即插入成功）
        if (updateCount > 0) {
            return ["state": 1, "Ascript": "插入成功", "data": true]
        } else {
            return ["state": 0, "Ascript": "插入失败", "data": false]
        }
    } catch (Exception e) {
        e.printStackTrace()
        return ["state": 0, "Ascript": "插入错误: ${e.message}", "data": false]
    } finally {
        if (conn != null) {
            conn.close()// 确保连接关闭
        }
    }
}

import java.util.Base64

def inputStreamToBase64(InputStream inputStream) {
    // 使用 ByteArrayOutputStream 来收集 InputStream 的所有数据
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()

    try {
        byte[] buffer = new byte[1024]
        int bytesRead
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, bytesRead)
        }

        // 将字节数组转换为 Base64 编码的字符串
        byte[] byteArray = byteArrayOutputStream.toByteArray()
        String base64Encoded = Base64.getEncoder().encodeToString(byteArray)

        return base64Encoded
    } finally {
        // 确保关闭流以释放资源
        byteArrayOutputStream.close()
        inputStream.close()
    }
}
import nccloud.open.api.auto.token.factory.APIUtilsFactory;
import nccloud.open.api.auto.token.factory.NCCVersionEnum;
import nccloud.open.api.auto.token.itf.IAPIUtils;

public class bip接口调用 {

}


class TokenTest {

    public static void main(String[] args) throws Exception {
        String _url = "nccloud/api/platform/attachmentcloudsync/queryAttachmentByBillId";

        String _json = "{\n" +
                "    \"billid\":\"1001A11000000005T3EH\",\n" +
                "    \"op_type\":[1]\n" +
                "}";
//        System.out.println(_json);

        String json = TokenTest.openapi(_url, _json);

//        System.out.println("json============" + json);
        String _return = TokenTest.openapi2(_url, _json, json);
//        System.out.println("_return============" + _return);
//        System.out.println(TokenTest.openapi2("nccloud/api/platform/attachmentcloudsync/download?pk_doc=9acdce29-3fec-4b18-91df-8fbfc0460a8f","", json));



    }

    public static String openapi(String urlStr, String jsonStr) throws Exception {
        IAPIUtils util = null;
        // 传参版本号或版本枚举获取工具类
        util = APIUtilsFactory.getAPIUtils(NCCVersionEnum.NCC2111);
        // 服务地址ip
        String ip = "10.1.1.226";
        // 服务端口号
        String port = "10088";
        // 账套编码，开发环境使用develop，生产环境需要使用用root账号登录，在“系统管理”节点查看账套编码
        String busi_center = "001";
        // 第三方应用编码
        String app_id = "ESB";
        // app_secret，用于请求加签
        String app_secret = "2aa7460b1ccc471a84f7";
        // 公钥，加解密使用
        String public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCFdcbMQJ2cHPIffjul8fSNM+WZvI4xz9FAoni5pSVqXaZAtTNIVxS2SUpj3byIMBbRoLqXkXyAF9G/TMErVwTaH0WEGpCEfLnU7acBMTimGpwjWmCTPwaiD0JqB14HYjegdSjt7BOVrLbV2e4oKzC/FMf0dTZh7gKmfg8hjhHKmyQD13npWRNB+/+9IQWZLs493JlfPSObYpPyX+WTCNBGqsAyme0MVoYMJ8RTyidylnBbShFBkNMB+Z4EYXtIX5dUiTDyu6RuOgAVilPR/UHMihTAtu8KMJWnXaSDym6y4QH9dw3tlJms6lwDeVDynTBYu/myiNn4pNBxUwDb9RQIDAQAB";
// ncc用户名
        String ncc_user = "Wangcs";
        // ncc用户密码
        String password = "";
        // 公有云租户id
        String tenant_id = null;
        // 加密等级
        String secret_level = "L0";
        // 授权模式，客户端模式为client，密码模式为：password
        String grant_type = "password";

        // 初始化方法1
        util.init(ip, port, busi_center, app_id, app_secret, public_key, ncc_user, password);
        // 初始化方法2，tenant_id、secret_level、grant_type这三个参数也可以通过setter注入
        // util.init(ip, port, busi_center, app_id, app_secret, public_key, ncc_user, password, tenant_id, secret_level, grant_type);

        // 获取token
        String token = util.getToken();
        return token;
    }

    public static String openapi2(String urlStr, String jsonStr, String token) throws Exception {
        IAPIUtils util = null;
        // 传参版本号或版本枚举获取工具类
        util = APIUtilsFactory.getAPIUtils(NCCVersionEnum.NCC2111);
        // 服务地址ip
        String ip = "10.1.1.226";
        // 服务端口号
        String port = "10088";
        // 账套编码，开发环境使用develop，生产环境需要使用用root账号登录，在“系统管理”节点查看账套编码
        String busi_center = "001";
        // 第三方应用编码
        String app_id = "ESB";
        // app_secret，用于请求加签
        String app_secret = "2aa7460b1ccc471a84f7";
        // 公钥，加解密使用
        String public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCFdcbMQJ2cHPIffjul8fSNM+WZvI4xz9FAoni5pSVqXaZAtTNIVxS2SUpj3byIMBbRoLqXkXyAF9G/TMErVwTaH0WEGpCEfLnU7acBMTimGpwjWmCTPwaiD0JqB14HYjegdSjt7BOVrLbV2e4oKzC/FMf0dTZh7gKmfg8hjhHKmyQD13npWRNB+/+9IQWZLs493JlfPSObYpPyX+WTCNBGqsAyme0MVoYMJ8RTyidylnBbShFBkNMB+Z4EYXtIX5dUiTDyu6RuOgAVilPR/UHMihTAtu8KMJWnXaSDym6y4QH9dw3tlJms6lwDeVDynTBYu/myiNn4pNBxUwDb9RQIDAQAB";
// ncc用户名
        String ncc_user = "Wangcs";
        // ncc用户密码
        String password = "";
        // 公有云租户id
        String tenant_id = null;
        // 加密等级
        String secret_level = "L0";
        // 授权模式，客户端模式为client，密码模式为：password
        String grant_type = "password";

        // 初始化方法1
        util.init(ip, port, busi_center, app_id, app_secret, public_key, ncc_user, password);
        // 初始化方法2，tenant_id、secret_level、grant_type这三个参数也可以通过setter注入
        // util.init(ip, port, busi_center, app_id, app_secret, public_key, ncc_user, password, tenant_id, secret_level, grant_type);

        // 请求的OpenAPI接口地址，注意nccloud前面没有"/"

        util.setApiUrl(urlStr);

        // 携带token访问接口，获取结果
        String result = util.getAPIRetrun(token, jsonStr);
        return result;
    }

}

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.*;

public class BIPFormUtilTest {
    private static final String DASH = "--";
    private static final String BOUNDARY = generateBoundary();
    private static final Charset CHARSET = StandardCharsets.UTF_8;
    private static final String NEW_LINE = "\r\n";
    private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";

    public static String generateBoundary() {
        return "----------" + UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 将 Base64 编码的字符串转换为 ByteArrayInputStream。
     *
     * @param base64String Base64 编码的字符串
     * @return ByteArrayInputStream 对象
     * @throws IOException 如果解码过程中发生错误
     */
    public static ByteArrayInputStream base64ToInputStream(String base64String) throws IOException {
        // 解码 Base64 数据
        byte[] decodedBytes = Base64.getDecoder().decode(base64String);

        // 返回 ByteArrayInputStream 对象
        return new ByteArrayInputStream(decodedBytes);
    }

    public static void writeMultipart(OutputStream out, String name, String value) throws IOException {
        StringBuilder content = new StringBuilder().append(DASH).append(BOUNDARY).append(NEW_LINE)
                .append("Content-Disposition: form-data; name=").append(name).append(NEW_LINE)
                .append("Content-Type: text/plain; charset=utf-8").append(NEW_LINE)
                .append(NEW_LINE)
                .append(value).append(NEW_LINE);

        out.write(content.toString().getBytes(CHARSET));
    }

    public static void writeMultipartFileStream(OutputStream out, String name, String filename, String contentType, String fileBase64) throws IOException {
        StringBuilder header = new StringBuilder().append(DASH).append(BOUNDARY).append(NEW_LINE)
                .append("Content-Disposition: form-data; name=").append(name).append("; filename=").append(filename).append(NEW_LINE)
                .append("Content-Type:").append(StringUtils.defaultString(contentType, DEFAULT_CONTENT_TYPE)).append(NEW_LINE)
                .append(NEW_LINE);
        out.write(header.toString().getBytes(CHARSET));

        byte[] buffer = new byte[8096];

        try (InputStream ins = base64ToInputStream(fileBase64)) {
            int count;
            while ((count = ins.read(buffer)) != -1) {
                out.write(buffer, 0, count);
            }
            out.write(NEW_LINE.getBytes(CHARSET));
        }
    }

    public static String getResponse(InputStream ins) {
        StringBuilder response = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(ins, StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return response.toString();
    }

    public static Map uploadFile(Map params) {
        println "上传方法开始"
        Map resultMap = new HashMap();
//        String tenantId = "m61ooyew";//租户id
        String tenantId = "";//租户id
        String appKey = "";
        String appSecret = "";
        String openApiUrl = "";//域名
        String tokenUrl = "";//token获取地址
        List<String> msgList = new ArrayList<>();//错误信息
        boolean isNeedTenantId = false;//是否需要租户id
        try {
            if (!params.containsKey("appKey") || params.get("appKey").toString().trim().equals("")) {
                msgList.add("appKey 不可为空.");
            }
            if (!params.containsKey("appSecret") || params.get("appSecret").toString().trim().equals("")) {
                msgList.add("appSecret 不可为空.");
            }
            if (!params.containsKey("openApiUrl") || params.get("openApiUrl").toString().trim().equals("")) {
                msgList.add("域名不可为空.");
            }
            if (msgList.size() > 0) {
                resultMap.put("status", "0");
                resultMap.put("msg", String.join(" ", msgList));
                return resultMap;
            }
            appKey = (String) params.get("appKey");
            appSecret = (String) params.get("appSecret");
            openApiUrl = (String) params.get("openApiUrl");
            tokenUrl = openApiUrl + "/iuap-api-auth";
            String access_token = new BIPFormUtilTest().getToken(tokenUrl, appKey, appSecret);
            if (access_token == null) {
                resultMap.put("status", "0");
                resultMap.put("msg", "文件上传失败：获取BIP接口令牌失败");
                return resultMap;
            }
            //调用文件上传接口
            Map paramsMap = new HashMap();
            paramsMap.put("access_token", access_token);
//            paramsMap.put("businessType", params.get("businessType"));//"diwork_yuncai"
//            paramsMap.put("businessId", params.get("businessId"));//"1cf057e7-bca3-43a9-9094-c343e6dfb7c0"
//            paramsMap.put("usePrivateBucket", params.get("usePrivateBucket"));//"1cf057e7-bca3-43a9-9094-c343e6dfb7c0"
//            paramsMap.put("resubmitCheckKey", "");//"1cf057e7-bca3-43a9-9094-c343e6dfb7c0"
            Map formParams = new HashMap();
//            System.out.println("上传附件地址="+(openApiUrl + "/iuap-api-gateway/yonbip/uspace/file/unique/upload" + plusUrlParams(paramsMap)));
            formParams.put("url", openApiUrl + "/iuap-api-gateway/yonbip/uspace/file/unique/upload" + plusUrlParams(paramsMap));
            println  "fileName:"+params.get("fileName")
            println  "usePrivateBucket:"+params.get("usePrivateBucket")
            println  "businessType:"+params.get("businessType")
            println  "businessId:"+params.get("businessId")
            formParams.put("fileName", params.get("fileName"));
            formParams.put("fileBase64", params.get("fileBase64"));
            formParams.put("usePrivateBucket", params.get("usePrivateBucket"));
            formParams.put("businessType", params.get("businessType"));//"diwork_yuncai"
            formParams.put("businessId", params.get("businessId"));//"1cf057e7-bca3-43a9-9094-c343e6dfb7c0"
            resultMap = httpForm(formParams);
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("status", "0");
            resultMap.put("msg", "文件上传失败：" + e.getMessage());
        }
        return resultMap;
    }

    public static Map deleteFile(Map params) {
        Map resultMap = new HashMap();
//        String tenantId = "m61ooyew";//租户id
        String tenantId = "";//租户id
        String appKey = "";
        String appSecret = "";
        String openApiUrl = "";//域名
        String tokenUrl = "";//token获取地址
        List<String> msgList = new ArrayList<>();//错误信息
        boolean isNeedTenantId = false;//是否需要租户id
        try {
            if (!params.containsKey("appKey") || params.get("appKey").toString().trim().equals("")) {
                msgList.add("appKey 不可为空.");
            }
            if (!params.containsKey("appSecret") || params.get("appSecret").toString().trim().equals("")) {
                msgList.add("appSecret 不可为空.");
            }
            if (!params.containsKey("openApiUrl") || params.get("openApiUrl").toString().trim().equals("")) {
                msgList.add("域名不可为空.");
            }
            if (msgList.size() > 0) {
                resultMap.put("status", "0");
                resultMap.put("msg", String.join(" ", msgList));
                return resultMap;
            }
            appKey = (String) params.get("appKey");
            appSecret = (String) params.get("appSecret");
            openApiUrl = (String) params.get("openApiUrl");
            tokenUrl = openApiUrl + "/iuap-api-auth";
            String access_token = new BIPFormUtilTest().getToken(tokenUrl, appKey, appSecret);
            if (access_token == null) {
                resultMap.put("status", "0");
                resultMap.put("msg", "文件上传失败：获取BIP接口令牌失败");
                return resultMap;
            }
            //调用文件上传接口
            Map paramsMap = new HashMap();
            paramsMap.put("access_token", access_token);
            paramsMap.put("businessType", params.get("businessType"));//"diwork_yuncai"
            paramsMap.put("businessId", params.get("businessId"));//"1cf057e7-bca3-43a9-9094-c343e6dfb7c0"
            paramsMap.put("fid", params.get("fid"));//文件ID
            resultMap = httpPost(tokenUrl + "/yonbip/uspace/iuap-apcom-file/rest/v1/file/delete", paramsMap, "{}");
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("status", "0");
            resultMap.put("msg", "文件删除失败：" + e.getMessage());
        }
        return resultMap;
    }

    public static String plusUrlParams(Map<String, String> paramMap) {
        StringBuilder param = new StringBuilder("?");
        try {
            if (paramMap != null) {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    param.append(entry.getKey());
                    param.append("=");
                    param.append(entry.getValue());
                    param.append("&");
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        param.deleteCharAt(param.length() - 1); // Remove trailing '&'
        return param.toString();
    }

    public static String accessToken;
    public static long tokenExpiryTime;

    public static String getToken(String adress, String appKey, String appSecret) {
        // Check if the current token is still valid
        try {
            if (accessToken == null || System.currentTimeMillis() >= tokenExpiryTime) {
                String requestUrl = adress + "/open-auth/selfAppAuth/getAccessToken";
//                System.out.println("requestUrl="+requestUrl);
                //https://yonbip.diwork.com/iuap-ipaas-base/ucgManage/baseapi/app/getToken?ts=1714962595033&appKey=6868e6559e2b4068b2e1c039591beaff&ytenantId=irf2v3c7&isAjax=1
                Map<String, String> params = new HashMap<>();
                // 除签名外的其他参数
                params.put("appKey", appKey);
                params.put("timestamp", String.valueOf(System.currentTimeMillis()));
                // 计算签名
                String signature = sign(params, appSecret);
//                System.out.println("signature=" + signature);
                params.put("signature", signature);
                String getString = doGet(requestUrl, params);
//                System.out.println("getString=" + getString);
//                String data = (String) getMap.get("data");
//                System.out.println("获取token: " + data);
                // 将json字符串转换为Map
                JSONObject json = JSONObject.parseObject(getString);
                if (json.get("code").equals("00000")) {
                    JSONObject dataObj = json.getJSONObject("data");
                    accessToken = (String) dataObj.get("access_token");
                    tokenExpiryTime = System.currentTimeMillis() + ((int) dataObj.get("expire") * 1000);
                } else {
                    accessToken = null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return accessToken;
    }

    /**
     * 按参数名排序后依次拼接参数名称与数值，之后对该字符串使用 HmacSHA256 加签，加签结果进行 base 64 返回
     *
     * @param params      请求参数 map
     * @param suiteSecret 套件密钥，用作 mac key
     * @return 签名
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     */
    public static String sign(Map<String, String> params, String suiteSecret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        // use tree map to sort params by name
        Map<String, String> treeMap;
        if (params instanceof TreeMap) {
            treeMap = params;
        } else {
            treeMap = new TreeMap<>(params);
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(suiteSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = Base64.getEncoder().encodeToString(signData);
        return URLEncoder.encode(base64String, "UTF-8");
    }

    public static SSLContext SSLCONTEXT = createSSLContext();

    public static String doGet(String requestUrl, Map<String, String> paramMap) throws IOException {
        StringBuilder param = new StringBuilder("?");
        if (paramMap != null) {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                param.append(entry.getKey());
                param.append("=");
                param.append(entry.getValue());
                param.append("&");
            }
            param.deleteCharAt(param.length() - 1); // Remove trailing '&'
        }

        // Create the URL with parameters
        URL url = new URL(requestUrl + param.toString());
        HttpURLConnection connection = null;
        StringBuilder responseString = new StringBuilder();
        try {
            connection = (HttpURLConnection) url.openConnection();
            HttpsURLConnection.setDefaultSSLSocketFactory(SSLCONTEXT.getSocketFactory());
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(86400000); // Set connection timeout
            connection.setReadTimeout(86400000);    // Set read timeout

            // Read the response

            try (BufferedReader ins = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
                String line;
                while ((line = ins.readLine()) != null) {
                    responseString.append(line);
                }
            }
        } finally {
            try {
                if (connection != null) {
                    connection.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return responseString.toString();
    }

    public static Map httpForm(Map params) {
        Map resultMap = new HashMap<>();
        HttpURLConnection conn = null;
        OutputStream out = null;
        long timestamp = System.currentTimeMillis();
        try {
            String urlStr = (String) params.get("url");
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            HttpsURLConnection.setDefaultSSLSocketFactory(SSLCONTEXT.getSocketFactory());
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Host", url.getHost());
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("transfer-encoding", "chunked");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
//            conn.setChunkedStreamingMode(200240);
            out = conn.getOutputStream();
//            formParams.put("usePrivateBucket", params.get("usePrivateBucket"));
//            formParams.put("businessType", params.get("businessType"));//"diwork_yuncai"
//            formParams.put("businessId", params.get("businessId"));
            writeMultipart(out, "businessType", (String) params.get("businessType"));
            writeMultipart(out, "businessId", (String) params.get("businessId"));
            writeMultipart(out, "usePrivateBucket", (String) params.get("usePrivateBucket"));
            writeMultipartFileStream(out, "files", (String) params.get("fileName"), null, (String) params.get("fileBase64"));
            out.write(new StringBuilder().append(DASH).append(BOUNDARY).append(DASH).append(NEW_LINE).toString().getBytes(CHARSET));
//            System.out.println("form data=" + out.toString());
            out.flush();
            String response
             if(conn.getResponseCode()==200){
                 response= getResponse(conn.getInputStream());
                 resultMap.put("status", "1");
                 resultMap.put("msg", "文件上传成功");
                 resultMap.put("data", response);
            }else{
                 response= getResponse(conn.getErrorStream());
                 println response
                 resultMap.put("status", "0");
                 resultMap.put("msg", "文件上传失败1");
                 resultMap.put("data", response);

             }

//            String utf8String = unicodeToUtf8(response);

        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("status", "0");
            resultMap.put("msg", "文件上传失败：" + e.getMessage());
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultMap;
    }

    public static Map<String, Object> httpPost(String urlStr, Map<String, String> paramMap, String jsonStr) {
        Map<String, Object> resultMap = new HashMap<>();
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        try {
            StringBuilder param = new StringBuilder("?");
            if (paramMap != null) {
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    param.append(entry.getKey());
                    param.append("=");
                    param.append(entry.getValue());
                    param.append("&");
                }
            }
            param.deleteCharAt(param.length() - 1); // Remove trailing '&'
            // 创建URL对象
            URL url = new URL(urlStr + param.toString());
            // 打开连接
            connection = (HttpURLConnection) url.openConnection();
            HttpsURLConnection.setDefaultSSLSocketFactory(SSLCONTEXT.getSocketFactory());
            // 设置请求方法
            connection.setRequestMethod("POST");
            // 设置请求头
            connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            // 允许输出
            connection.setDoOutput(true);

            // 发送请求数据
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonStr.getBytes("utf-8");
                os.write(input, 0, input.length);
            }

            // 获取响应码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取响应内容
                try (BufferedReader ins = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = ins.readLine()) != null) {
                        response.append(line.trim());
                    }
                    System.out.println("待办任务报文=" + response.toString());
                    // 设置响应结果
                    resultMap.put("status", "1");
                    resultMap.put("msg", "");
                    resultMap.put("data", response.toString());
                }
            } else {
                resultMap.put("status", "0");
                resultMap.put("msg", "HTTP错误码：" + responseCode);
                resultMap.put("data", null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("status", "0");
            resultMap.put("msg", "发送POST请求报错：" + e.getMessage());
            resultMap.put("data", null);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return resultMap;
    }

    /**
     * 创建一个信任所有证书的 SSLContext 实例
     *
     * @return 信任所有证书的 SSLContext 实例
     * @throws Exception 如果初始化 SSLContext 时发生错误
     */
    public static SSLContext createSSLContext() {
        // 创建一个 TrustManager，信任所有证书
        try {
            TrustManager[] trustAll = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            // 不做检查
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            // 不做检查
                        }
                    }
            };
            // 创建一个 SSLContext 并初始化
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAll, new java.security.SecureRandom());

            return sslContext;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将文件转换为 Base64 编码的字符串。
     *
     * @param file 文件对象
     * @return Base64 编码的字符串
     * @throws IOException 如果文件读取过程中发生错误
     */
    public static String fileToBase64(File file) {
        // 检查文件是否存在
        if (!file.exists() || !file.isFile()) {
            throw new IllegalArgumentException("文件不存在或不是一个有效的文件");
        }

        // 读取文件内容并转换为 Base64 字符串
        byte[] fileBytes = null;
        try {
            fileBytes = readFileToByteArray(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return Base64.getEncoder().encodeToString(fileBytes);
    }

    /**
     * 将文件内容读取为字节数组。
     *
     * @param file 文件对象
     * @return 字节数组
     * @throws IOException 如果文件读取过程中发生错误
     */
    private static byte[] readFileToByteArray(File file) throws IOException {
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] fileBytes = new byte[(int) file.length()];
            fis.read(fileBytes);
            return fileBytes;
        }
    }

    public static String getBase64String() {
        StringBuilder contentBuilder = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\2021-12-24\\项目集合\\百诺医药\\1.txt"), "UTF-8"))) {
            String line;
            while ((line = br.readLine()) != null) {
                contentBuilder.append(line).append(System.lineSeparator());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        String content = contentBuilder.toString();
        return content;
    }

    public static void decodeBase64ToFile(String base64String, String filePath) {
        // 解码 Base64 字符串
        byte[] data = Base64.getDecoder().decode(base64String);

        // 将字节数组写入文件
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            fos.write(data);
            System.out.println("文件已成功写入到: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //分页查询人员待办任务
    public static Map querytaskstodo(Map params) {
        Map resultMap = new HashMap();
//        String tenantId = "m61ooyew";//租户id
        String tenantId = "";//租户id
        String appKey = "";
        String appSecret = "";
        String openApiUrl = "";//域名
        String tokenUrl = "";//token获取地址
        List<String> msgList = new ArrayList<>();//错误信息
        boolean isNeedTenantId = false;//是否需要租户id
        try {
            if (!params.containsKey("appKey") || params.get("appKey").toString().trim().equals("")) {
                msgList.add("appKey 不可为空.");
            }
            if (!params.containsKey("appSecret") || params.get("appSecret").toString().trim().equals("")) {
                msgList.add("appSecret 不可为空.");
            }
            if (!params.containsKey("openApiUrl") || params.get("openApiUrl").toString().trim().equals("")) {
                msgList.add("域名不可为空.");
            }
            if (msgList.size() > 0) {
                resultMap.put("status", "0");
                resultMap.put("msg", String.join(" ", msgList));
                return resultMap;
            }
            appKey = (String) params.get("appKey");
            appSecret = (String) params.get("appSecret");
            openApiUrl = (String) params.get("openApiUrl");
            tokenUrl = openApiUrl + "/iuap-api-auth";
            String access_token = new BIPFormUtilTest().getToken(tokenUrl, appKey, appSecret);
            if (access_token == null) {
                resultMap.put("status", "0");
                resultMap.put("msg", "分页查询人员待办任务失败：获取BIP接口令牌失败");
                return resultMap;
            }
            //调用接口
            Map paramsMap = new HashMap();
            paramsMap.put("access_token", access_token);
            Map userParams = new HashMap();
            userParams.put("userIds", Arrays.asList("d86b0a62-ce88-4ca9-969c-4828f7e785b7", "7fbb00bd-41a4-4115-b254-d53803996b78"));
            resultMap = httpPost(tokenUrl + "/yonbip/digitalModel/staffQry/tPlus/getStaffListByUserIds?access_token=" + access_token, null, JSON.toJSONString(userParams, SerializerFeature.DisableCircularReferenceDetect));
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("status", "0");
            resultMap.put("msg", "分页查询人员待办任务失败：" + e.getMessage());
        }
        return resultMap;
    }


    public static void main(String[] args) {
        String appKey = "d42bf79ccfcd49fa8c001f15b208b8cd";
        String appSecret = "7c70c9c39e70300e3496770e9c5bbffb47280dfc";
        String openApiUrl = "https://srm.bestcomm.cn:11443";
        Map paramMap = new HashMap();
        paramMap.put("appKey", appKey);
        paramMap.put("appSecret", appSecret);
        paramMap.put("openApiUrl", openApiUrl);
        paramMap.put("businessType", "diwork_yuncai");
        paramMap.put("businessId", "hc6121po_20_1001A11000000007D1GG");
        paramMap.put("usePrivateBucket", "true");
        paramMap.put("fileName", "contract.pdf");
        paramMap.put("fileBase64", fileToBase64(new File("E:\\2021-12-24\\项目集合\\百诺医药\\契约锁文档\\contract.pdf")));
        Map uploadResult = BIPFormUtilTest.uploadFile(paramMap);
    }
}